package com.ruoyi.tester.service.impl;

import com.ruoyi.tester.domain.*;
import com.ruoyi.tester.executor.IExtraHandler;
import com.ruoyi.tester.executor.InterfaceExecutorUtil;
import com.ruoyi.tester.executor.http.HttpUtils;
import com.ruoyi.tester.executor.http.HttpUtilsFactory;
import com.ruoyi.tester.executor.http.XzfHttpResult;
import com.ruoyi.tester.login.LoginCache;
import com.ruoyi.tester.mapper.TesterExecutorMapper;
import com.ruoyi.tester.mapper.TesterLoginConfigMapper;
import com.ruoyi.tester.service.ITesterExecutorService;
import com.ruoyi.tester.swagger.SwaggerParserFactory;
import com.ruoyi.tester.swagger.SwaggerParser;
import org.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author SongJun
 * @description TODO:
 * @date 2022/4/15 11:09
 */
@Service
public class TesterExecutorServiceImpl implements ITesterExecutorService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    TesterExecutorMapper testerExecutorMapper;
    @Autowired
    IExtraHandler extraHandler;
    @Autowired
    TesterLoginConfigMapper testerLoginConfigMapper;

    @Override
    public void executeTesterTask(Long taskId) {
        List<TaskInterfaceFullInfo> list = testerExecutorMapper.selectTaskInterfaceByTaskId(taskId);
        List<TaskInterfaceEffectiveInfo> effectiveList = list.stream().map(x -> new TaskInterfaceEffectiveInfo(x)).collect(Collectors.toList());
        TaskCallLog taskCallLog = new TaskCallLog(taskId, effectiveList.size(),0);
        testerExecutorMapper.insertTesterTaskCallLog(taskCallLog);
        Map<Long, String> calledStatus = new ConcurrentHashMap<>();

        Set<Long> thisRelationIdSet = effectiveList.stream().map(x -> x.getRelationId()).collect(Collectors.toSet());

        for (TaskInterfaceEffectiveInfo item : effectiveList){
            item.setTaskCallLogId(taskCallLog.getTaskCallLogId());

            missDependRelation(item, thisRelationIdSet);

            if(item.getDependRelationIdList().isEmpty()){
                calledStatus.put(item.getRelationId(), IExtraHandler._PROCESSING_);
                InterfaceExecutorUtil.callInterface(item, extraHandler, effectiveList, calledStatus);
            }
        }
    }

    //是否缺失要执行的依赖关系
    private boolean missDependRelation(TaskInterfaceEffectiveInfo item, Set<Long> thisRelationIdSet){
        boolean missDependRelation = false;
        for (Long dependRelationId : item.getDependRelationIdList()) {
            if (!thisRelationIdSet.contains(dependRelationId)) {
                missDependRelation = true;
            }
        }
        if (missDependRelation) {
            InterfaceCallLog interfaceCallLog = new InterfaceCallLog(item, null, null, null, "依赖接口缺失");
            interfaceCallLog.setStatus(InterfaceCallStatus.FAULT);
            extraHandler.saveResult(interfaceCallLog, TaskCallProgres.FAULT);
        }
        return missDependRelation;
    }

    @Override
    public List<TesterInterface> swaggerSearch(String swaggerResourcesUrl) {
        List<TesterInterface> ret = new ArrayList();
        HttpUtils httpUtils = HttpUtilsFactory.getHttpUtils();
        XzfHttpResult result = httpUtils.get(swaggerResourcesUrl, null, null, null, null);
        if(result != null && result.isSuccess()){
            JSONArray ja = new JSONArray(result.getBody());
            String swaggerVersion = ja.getJSONObject(0).getString("swaggerVersion");
            String url = ja.getJSONObject(0).getString("url");
            swaggerResourcesUrl = swaggerResourcesUrl.replace("swagger-resources", url);
            result = httpUtils.get(swaggerResourcesUrl, null, null, null, null);

            SwaggerParser parser = SwaggerParserFactory.getInstance(swaggerVersion, result.getBody());
            if(parser != null) {
                ret = parser.parse();
            }
        }
        return ret;
    }

    @Override
    public List<TaskCallLogOut> getTaskLog() {
        List<TaskCallLogOut> taskLog = testerExecutorMapper.getTaskLog();
        return taskLog;
    }

    @PostConstruct
    void init(){
        LoginCache.initTesterLoginConfigMapper(testerLoginConfigMapper);
    }
}
